home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
PACKET
/
TFPCX2IP
/
TFPCX2IP.ASM
< prev
Wrap
Assembly Source File
|
1997-10-25
|
27KB
|
994 lines
.model large
.8086
;.stack 100h
ax25_code segment word public
assume cs:ax25_code, ds:ax25_code
org 2ch
phd_environ dw ?
szczyt_kolejki EQU 216Eh
org 100h
start: jmp install_driver
txt1: db 'TFPCX-2-TCP/IP Version 0.4b',13,10
db 'Packet driver that allows using TFPCX with NOS software',13,10
db '(C) 1995 by Piotrek Kaczmarzyk, SQ6BOT',13,10,10
db 'This little piece of code is a CARDWARE - please read DOC file',13,10
db 'Free license granted to radio amateurs only.',13,10,10,'$'
txt2: db 'TFPCX V2.0 detected.',13,10,'$'
txt3: db 'Error: This program works only with TFPCX V2.0.',13,10,'$'
txt4: db 'Error: TFPCX not loaded.',13,10,'$'
host: db 'Switching TFPCX to Host Mode.',13,10,'$'
JHOST: db 27,'JHOST1',13
JHOSTend:
count dw 0
packet_int_no db 60h ; default packet interrupt number
bak_es dw 0
bak_si dw 0
bak_cx dw 0
bufadr dw 0
bufseg dw 0
bufofs dw 0
data_s dw 0
s_len dw 0 ; dlugosc ramki
s_frm dw 0 ; adres obecnie analizowanej ramki
s_pos dw 0 ; pozycja w ramce
s_pos_org dw 0
s_prev dw 0 ; poprzednia ramka
s_cnt dw 0
HostMode:
mov bx,offset JHOST
nxt: mov ah,3
mov al,[bx]
int 0FDh
inc bx
cmp bx,offset JHOSTend
jne nxt
ret
;==========================================================================
proc_5E60:
lea ax,[bx+28h]
mov [bx+08h],ax
mov word ptr [bx+0Ch],0000h
ret
proc_5E6C:
push bp
mov bp,sp
sub sp,0004h
pushf
cli
mov ax,ds:[14E8h]
dec word ptr ds:[14E8h]
or ax,ax
jnz loc_5E82
stc
jmp return
; < ERROR - NO MORE FREE BUFFERS
loc_5E82:
mov bx,ds:[12F2h]
call proc_5E94
mov [bp-02h],ax
popf
mov ax,[bp-02h]
clc
return:
mov sp,bp
pop bp
ret
create_frame:
push ax
push bx
push cx
push si
mov bx,ax
add_next_char:
cmp cx,0000h
je w_buforze
mov al,es:[si]
push bx
call proc_5E0A ; al = char, bx = buffer address
pop bx
dec cx
inc si
jmp add_next_char
w_buforze:
pop si
pop cx
pop bx
pop ax
ret
proc_5E0A:
push bp
mov bp,sp
push ax
push si
mov si,bx
mov ax,[si+0Ah]
inc word ptr [si+0Ah]
test al,1Fh
jnz loc_5E2C
call proc_5E6C
mov bx,ax
mov ax,[si+06h]
call proc_5EB6
add ax,0004h
mov [si+08h],ax
loc_5E2C:
mov al,[bp-02h]
mov bx,[si+08h]
mov [bx],al
inc word ptr [si+08h]
pop si
mov sp,bp
pop bp
ret
sendpkt:
call rst_ds
call proc_5E6C ; allocate
call create_frame
mov bx,ax
call proc_5E60 ; refresh
mov ax,ds:[2034]
mov [si+0Eh],ax
mov byte ptr [bx+10h],02h
mov byte ptr [bx+11h],00h
mov byte ptr [bx+12h],00h ; nr_modemu = [14E6]
call proc_5834 ; send_it
clc
mov dh,NO_ERROR
ret
rst_ds:
push cs
pop ds
push ax
mov ax,data_s
mov ds,ax
pop ax
ret
no_more_buffers:
jmp pkterror
proc_5834:
push bp
mov bp,sp
sub sp,0002h
push bx
push si
mov al,[bx+12h]
sub ah,ah
mov [bp-02h],ax
mov si,ax
shl si,1
inc word ptr [si+1470h]
cmp word ptr ds:[14E8h],0040h
jbe out_of_buffers
call proc_5E60
pushf
cli
mov bx,[bp-02]
shl bx,1
shl bx,1
mov ax,[bx+1532h]
mov bx,[bp-04]
call proc_5EB6
mov bx,[bp-02]
cmp byte ptr [bx+78DEh],00h
jnz problems
mov ax,bx
call final_send
jmp koncowka
problems:
mov byte ptr [bx+1FFCh],01h
koncowka:
popf
pop si
mov sp,bp
pop bp
ret
out_of_buffers:
mov bx,[bp-04h]
mov ax,ds:[2170h]
call proc_5EB6
pop si
mov sp,bp
pop bp
ret
final_send:
push bp
mov bp,sp
sub sp,0002h
push ax
cmp al,ds:[201Eh]
jb loc1
jmp something
loc1:
mov bl,al
sub bh,bh
cmp [bx+20E6h],bh
jnz loc2
jmp something
loc2:
shl bx,1
cmp byte ptr [bx+798Eh],00h
jz loc3
mov al,30h
mul byte ptr [bx+798Fh]
mov bx,ax
mov word ptr [bx+78ACh],0001h
mov sp,bp
pop bp
ret
loc3:
mov bl,[bp-04h]
sub bh,bh
shl bx,1
mov al,1Ch
mul byte ptr [bx+798Fh]
mov bx,ax
add bx,20FEh
mov [bp-02h],bx
cmp byte ptr [bx+0Ah],00h
jz something
pushf
cli
mov bx,[bp-02h]
mov al,[bx+14h]
sub ah,ah
jmp loc4
loc10:
mov bl,[bp-04h]
sub bh,bh
cmp [bx+1518h],bh
jz loc9
loc6:
mov ax,0001h
loc5:
mov bx,[bp-02h]
mov [bx+16h],ax
mov bx,[bp-02h]
mov byte ptr [bx+14h],01h
jmp loc7
loc9:
mov bl,[bp-04h]
sub bh,bh
cmp [bx+20D6h],bh
jz loc6
mov al,[bx+20D6h]
sub ah,ah
jmp loc5
loc8:
mov bx,[bp-02h]
mov word ptr [bx+16h],0001h
mov byte ptr [bx+14h],02h
jmp loc7
loc4:
or ax,ax
jz loc10
sub ax,0005h
jz loc8
loc7:
popf
mov sp,bp
pop bp
ret
something:
mov ah,[bp-04h]
sub al,al
or ax,8001h
call proc_5D62
mov sp,bp
pop bp
ret
proc_5D62:
push di
push si
mov dx,ax
mov cl,08h
mov si,ax
and si,7F00h
shr si,cl
mov ax,si
shl si,1
add si,1520h
mov di,ax
shl di,1
shl di,1
add di,1530h
cmp word ptr [si],0000h
je loc_a
mov bx,[si]
mov ax,ds:[2170h]
call proc_5EB6
mov word ptr [si],0000h
loc_a: mov bx,di
call proc_5DF0
pop si
pop di
ret
proc_5DF0:
push si
cmp [bx],bx
je loc_b
mov si,bx
loc_c: mov bx,[si]
call proc_5E94
mov bx,ax
mov ax,ds:[2170h]
call proc_5EB6
cmp [si],si
jne loc_c
loc_b: pop si
ret
proc_5E94:
push bp
mov bp,sp
push bx
push si
pushf
cli
mov bx,[bp-02h]
mov ax,[bx]
mov si,[bx+2]
mov [si],ax
mov ax,[bx+02h]
mov bx,[bx]
mov [bx+02h],ax
popf
mov ax,[bp-02h]
pop si
mov sp,bp
pop bp
ret
proc_5EB6:
push bp
mov bp,sp
push ax
push bx
push di
push si
pushf
cli
mov bx,[bp-02h]
mov ax,[bx]
mov si,[bp-04h]
mov [si],ax
mov [si+02h],bx
mov di,[si]
mov [di+02h],si
mov [bx],si
popf
mov ax,[bp-04h]
pop si
pop di
mov sp,bp
pop bp
ret
;=====================================================
; RECEIVING PART
;=====================================================
doupcallnow:
pushf
push bp
push bx
push ax
push cx
push dx
push di
push si
push ds
push es
mov bx,szczyt_kolejki
next_frame:
call rst_ds
mov bx,[bx]
mov cx,bx
cmp bx,szczyt_kolejki
jne short is_packet
jmp no_packet
is_packet:
call rst_ds
call proc_5E60 ; refresh
push cs
pop ds
mov count,0
copy_next_byte:
call rst_ds
mov ax,[bx+0Ch]
cmp ax,[bx+0Ah]
je copy_end
call proc_5E3C
push bx
push cs
pop ds
mov bx,offset buf
add bx,count
cmp bx,offset over_buf
jae no_packet2
mov ds:[bx],al
inc count
pop bx
jmp copy_next_byte
no_packet2:
pop bx
jmp no_packet
copy_end:
push cs
pop ds
push bx
call DoUpCall
pop bx
; mov [bx+28h],0A8A8h
jmp next_frame
no_packet:
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop ax
pop bx
pop bp
popf
mov [bp-08h],ax
cmp ax,szczyt_kolejki
db 0EAh,0B1h,46h
jump2: dw 0
proc_5E3C:
push si
mov ax,[bx+0Ch]
inc word ptr [bx+0Ch]
test al,1Fh
jnz loc_z
mov si,[bx+08h]
mov ax,[si-24h]
add ax,0004h
mov [bx+08h],ax
loc_z:
mov si,[bx+08h]
inc word ptr [bx+08h]
mov al,[si]
sub ah,ah
pop si
ret
drvr_class db 9 ;driver's class - default is 9 that is AX.25
driver_name db 'Packet driver overlay for TFPCX',0
even
old_packet_int dw 0,0 ;saves software interrupt vector
receive_upcall dw 0,0 ;keeps application "upcall" routine address
;==============================================================
;Service routine for software interrupt to control the driver
; Packet Driver Error numbers
NO_ERROR equ 0 ;no error at all.
BAD_HANDLE equ 1 ;invalid handle number
NO_CLASS equ 2 ;no interfaces of specified class found
NO_TYPE equ 3 ;no interfaces of specified type found
NO_NUMBER equ 4 ;no interfaces of specified number found
BAD_TYPE equ 5 ;bad packet type specified
NO_MULTICAST equ 6 ;this interface does not support multicast
CANT_TERMINATE equ 7 ;this packet driver cannot terminate
BAD_MODE equ 8 ;an invalid receiver mode was specified
NO_SPACE equ 9 ;operation failed because of insufficient space
TYPE_INUSE equ 10 ;the type had previously been accessed, and not released.
BAD_COMMAND equ 11 ;the command was out of range, or not implemented
CANT_SEND equ 12 ;the packet couldn't be sent (usually hardware error)
CANT_SET equ 13 ;hardware address couldn't be changed (more than 1 handle open)
BAD_ADDRESS equ 14 ;hardware address has bad length or format
CANT_RESET equ 15 ;Couldn't reset interface (more than 1 handle open).
BAD_IOCB equ 16 ;an invalid iocb was specified
regs_w struc ; stack offsets of incoming regs
_ES dw ?
_DS dw ?
_bp dw ?
_DI dw ?
_SI dw ?
_DX dw ?
_CX dw ?
_BX dw ?
_AX dw ?
_IP dw ?
_CS dw ?
_F dw ? ; flags, Carry flag is bit 0
regs_w ends
CY equ 0001h
EI equ 0200h
regs_b struc ; stack offsets of incoming regs
dw ? ; es, ds, bp, di, si are 16 bits
dw ?
dw ?
dw ?
dw ?
_DL db ?
_DH db ?
_CL db ?
_CH db ?
_bl db ?
_bh db ?
_AL db ?
_AH db ?
regs_b ends
DRVR_ISR: ;service interrupt vector points here
;application layer calls enter this point
;via a software interrupt
jmp exec_command ;entry point must be a jump
db 'PKT DRVR',0 ;followed by this string
exec_command: ;packet driver command executor
sti ;don't lock interrupts
push ax ;save registers on stack
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
mov bp,sp ;bp=sp so we can address pushed registers
and _F[bp],not CY ;Clear carry on exit
mov bx,cs ;make ds=cs
mov ds,bx
mov bl,ah ;execute command given by ah
mov bh,0
cmp bx,26
jnc f_above_25
add bx,bx
call [functions+bx]
DRVR_ISR_return:
mov _DH[bp],dh ;pass dh-now to dh-on-exit
sbb ax,ax
and ax,CY
or _F[bp],ax ;pass carry-now to carry-on-exit
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
f_above_25:
call f_not_implemented
jmp short DRVR_ISR_return
even
functions label word
dw f_not_implemented ;0
dw f_driver_info ;1
dw f_access_type ;2
dw f_release_type ;3
dw f_send_pkt ;4
dw f_terminate ;5
dw f_get_address ;6
dw f_reset_interface ;7
dw f_stop ;8
dw f_not_implemented ;9
dw f_get_parameters ;10
dw f_not_implemented ;11
dw f_as_send_pkt ;12
dw f_drop_pkt ;13
dw f_not_implemented ;14
dw f_not_implemented ;15
dw f_not_implemented ;16
dw f_not_implemented ;17
dw f_not_implemented ;18
dw f_not_implemented ;19
dw f_set_rcv_mode ;20
dw f_get_rcv_mode ;21
dw f_set_multicast_list ;22
dw f_get_multicast_list ;23
dw f_get_statistics ;24
dw f_set_address ;25
f_driver_info:
mov dh,drvr_class ;driver class
mov _CH[bp],dh
mov _AL[bp],1 ;basic flag
mov _DX[bp],0 ;driver type
mov _CL[bp],0 ;driver number
mov _BX[bp],0 ;driver version
mov _DS[bp],ds ;driver name pointer
mov _SI[bp],offset driver_name
mov dh,NO_ERROR
clc
ret
f_access_type:
mov bx,_BX[bp]
cmp al,drvr_class ;our class ?
jnz wrong_class
cmp bx,0FFFFh ;generic type ?
jz type_OK
cmp bx,0 ;our type ?
jnz wrong_type
type_OK:
cmp dl,0 ;generic num ?
jnz wrong_num
mov ax,receive_upcall ;check if handle busy
or ax,receive_upcall+2
jnz busy_handle
mov receive_upcall,di ;store receiver upcall
mov ax,es
mov receive_upcall+2,ax
mov _AX[bp],0 ;return handle=0
clc
mov dh,NO_ERROR
ret
wrong_class:
stc
mov dh,NO_CLASS
ret
wrong_type:
stc
mov dh,NO_TYPE
ret
wrong_num:
stc
mov dh,NO_NUMBER
ret
busy_handle:
stc
mov dh,TYPE_INUSE
ret
pkterror:
stc
mov dh,CANT_SEND
ret
f_stop: jmp short clear_upcall
f_release_type:
cmp _BX[bp],0 ;handle=0 ?
jnz wrong_handle
mov ax,receive_upcall ;is receiver upcall defined?
or ax,receive_upcall+2
jz wrong_handle ;jump if not
clear_upcall:
xor ax,ax ;receiver upcall := 0:0
mov receive_upcall,ax ;this means "upcall address is not valid"
mov receive_upcall+2,ax
clc
mov dh,NO_ERROR
ret
wrong_handle:
stc
mov dh,BAD_HANDLE
ret
f_send_pkt:
mov es,_DS[bp] ;es:si=packet address, cx=packet length
jmp sendpkt
f_terminate:
clc
mov dh,NO_ERROR
ret
f_get_address:
xor cx,cx ;return zero-length address
clc
mov dh,NO_ERROR
ret
f_reset_interface: jmp short f_not_implemented
f_get_parameters: jmp short f_not_implemented
f_as_send_pkt: jmp short f_not_implemented
f_drop_pkt: jmp short f_not_implemented
f_set_rcv_mode: jmp short f_not_implemented
f_get_rcv_mode: jmp short f_not_implemented
f_set_multicast_list: jmp short f_not_implemented
f_get_multicast_list: jmp short f_not_implemented
f_get_statistics: jmp short f_not_implemented
f_set_address: jmp short f_not_implemented
f_not_implemented: ;non-implemented functions jump here
stc ;set carry to indicate an error
mov dh,BAD_COMMAND ;error code = BAD_COMMAND
ret
DoUpCall: ;input: RxFrameData contains a valid packet (CRC is OK)
; RxFrameLen contains its length
push ds
push es
push si
push di
mov cx,count ;load packet length
mov ax,receive_upcall ;is there a valid upcall address ?
or ax,receive_upcall+2
jz DoUpCall_ret ;jump if there is not
mov ax,0 ;flag=0 - first upcall
mov bx,0 ;handle = 0
mov di,0 ;set es:di = NULL
mov es,di
call dword ptr [receive_upcall] ;first upcall
mov ax,es ;check if application returned
or ax,di ;valid buffer pointer
jz DoUpCall_ret ;jump if not
mov si,di ;make si=di before we alter di (for second upcall)
mov bx,offset buf ;copy the packet to es:di
mov cx,count ;packet length (exclude CRC)
CopyLoop: mov al,[bx] ;loop over packet bytes
inc bx ;would movsb do the job ?
mov es:[di],al
inc di
loop CopyLoop
mov cx,count ;again packet len for second call
mov ax,es ;make ds=es (is not same as cs now !)
mov ds,ax
mov bx,0 ;handle 0
mov ax,1 ;flag=1 - second upcall
call dword ptr cs:[receive_upcall] ;second upcall
;we have to use cs: addressing in above call because we modified ds
DoUpCall_ret:
pop di
pop si
pop es
pop ds
ret
buf:
db 200h dup (?)
over_buf:
print_following_string: ;prints string following the call - modifies bx !
;string must following "call print_following_string"
;_must_ end with NULL character !
pop bx ;pop return address from the stack
push ax ;so we know where the char. string is
push dx
print_next_char:
mov dl,cs:[bx] ;load next character
inc bx
and dl,dl ;NULL char ?
jz string_end ;exit this loop if so
mov ah,2 ;otherwise print it
int 21h
jmp short print_next_char
string_end:
pop dx
pop ax
push bx ;push new return address on stack
ret
SkipBlanks: ;mov to first non-SPACE nor TAB char.
;ds:[bx] = string address
SkipThisChar:
mov al,es:[bx] ;load next char.
inc bx ;increment pointer
cmp al,' ' ;space ?
jz SkipThisChar ;jump if SPACE
cmp al,9 ;TAB ?
jz SkipThisChar ;jump if TAB
dec bx ;if not SPACE nor TAB move pointer back
ret ;ds:bx=address of non-blank character
;al=this character
ReadOptions:
push ax
push bx
push cx
push dx
mov bx,81h ;load offset to command line arguments
NextOption:
call SkipBlanks ;al=next non-blank char
cmp al,13 ;carriage return ?
clc
jz ReadOptions_ret
cmp al,'-' ;minus sign ?
jz InterpreteOption ;if so go and interprete following chars
ReadOptions_err:
stc
ReadOptions_ret:
pop dx
pop cx
pop bx
pop ax
ret ;carry=1 => results are _not_ valid
InterpreteOption: ;interprete an option
;ds:bx=address of '-' char.
inc bx
mov al,es:[bx] ;load char after '-'
inc bx ;move pointer futher
cmp al,'?'
je OptionUsage
cmp al,'i'
je Opt_interrupt
call UnknownOption ;if non of the above says the option
;was not recognized
jmp ReadOptions_err
Opt_interrupt:
call ReadHexNumber
mov packet_int_no,dl
jmp short NextOption
OptionUsage:
call Print_following_string
db 'Usage:',10,10,13
db ' -? - this help text',10,13
db ' -i<hex_int_no> - set interrupt vector',10,13
db 10,0
clc
jmp NextOption
UnknownOption: ;say the option not recognized
push bx
call Print_following_string
db 'Unknown option: -',0
mov dl,al
mov ah,2
int 21h
call Print_following_string
db 13,10,0
pop bx
ret
ReadHexDigit: ;es:bx = digit pointer
mov al,es:[bx]
cmp al,'0'
jc ReadHexDigit_ret ;jump if below '0'
cmp al,'9'+1
cmc
jc ReadHexDigit_lett ;jump if above '9'
sub al,'0'
jmp short ReadHexDigit_ret
ReadHexDigit_lett:
cmp al,'a'
jc ReadHexDigit_ret ;jump if below 'a'
cmp al,'f'+1
cmc
jc ReadHexDigit_ret ;jump if above 'f'
sub al,'a'-10
ReadHexDigit_ret:
ret ;carry=1 => not a hex digit, al=char.
;carry=0 => hex digit indeed, al=value
ReadHexNumber:
push cx
mov cl,4
mov dx,0
ReadNextHexDigit:
call ReadHexDigit
jc ReadHexNumber_ret
inc bx
shl dx,cl ;multiply dx by 16
or dl,al ;add the digit just read
jmp short ReadNextHexDigit
ReadHexNumber_ret:
pop cx
ret ;dx=the number,
;ds:bx *char where the interpretation stopped
;al=this character
install_driver:
call ReadOptions
jnc DoPrintParam
jmp BadUsage
DoPrintParam:
; call PrintParameters
;--------------------------------
push ds
push cs
pop ds
mov ah,09h
mov dx,offset txt1
int 21h
mov ax,35FDh
int 21h
mov si,bx
mov ax,es:[si+4]
cmp ax,4E35h
jne no_tfpcx
mov ah,0FEh
int 0FDh
cmp ax,0200h
jne no_v2
mov ah,09h
mov dx,offset txt2
int 21h
pop es
call ReadOptions
xor ax,ax
mov es,ax
mov si,8*4+2
mov ax,es:[si]
mov ds,ax
cli
mov bx,46Abh
mov byte ptr [bx],0EAh
mov word ptr [bx+1],offset doupcallnow
mov word ptr [bx+3],cs
mov cx,ds:[0FC0h]
mov ax,ds
push cs
pop ds
mov bx,offset jump2
mov [bx],ax
mov data_s,cx
sti
mov ah,25h
mov al,packet_int_no
mov dx,offset DRVR_ISR
int 21h
mov dx,offset host
mov ah,9
int 21h
call HostMode
mov ah,31h
mov dx,offset koniec
shr dx,1
int 21h
no_v2:
mov dx,offset txt3
jmp no_
no_tfpcx:
mov dx,offset txt4
no_:
mov ah,09h
int 21h
n33: mov ax,4C01h
int 21h
BadUsage:
call print_following_string
db 'Bad options - type TFPCX2IP -? to get info',13,10,0
jmp n33
koniec:
ends ax25_code
end start